﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace OF.Utility
{
    /// <summary>
    /// 把枚举值按照指定的文本显示
    /// </summary>
    /// <example>
    /// [EnumDescription("中文数字")]
    /// enum MyEnum
    /// {
    ///        [EnumDescription("数字一")]
    ///        One = 1, 
    ///        [EnumDescription("数字二")]
    ///        Two,
    ///        [EnumDescription("数字三")]
    ///        Three
    /// }
    /// EnumDescription.GetEnumText(typeof(MyEnum));
    /// EnumDescription.GetFieldText(MyEnum.Two);
    /// EnumDescription.GetFieldTexts(typeof(MyEnum)); 
    /// 绑定到下拉框：
    /// comboBox1.DataSource = EnumDescription.GetFieldTexts(typeof(OrderStateEnum));
    /// comboBox1.ValueMember = "EnumValue";
    /// comboBox1.DisplayMember = "EnumDisplayText";
    /// comboBox1.SelectedValue = (int)OrderStateEnum.Finished;  //选中值
    /// </example>
    /// <remarks>
    /// 一般通过枚举值的ToString()可以得到变量的文本，
    /// 但是有时候需要的到与之对应的更充分的文本，
    /// 这个类帮助达到此目的
    /// </remarks>
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Enum)]
    public class EnumDescription : Attribute
    {

        private string enumDisplayText;
        private int enumRank;
        private FieldInfo fieldIno;



        /// <summary>
        /// 描述枚举值
        /// </summary>
        /// <param name="enumDisplayText">描述内容</param>
        /// <param name="enumRank">排列顺序</param>

        public EnumDescription(string enumDisplayText, int enumRank)
        {
            this.enumDisplayText = enumDisplayText;
            this.enumRank = enumRank;
        }



        /// <summary>
        /// 描述枚举值，默认排序为5
        /// </summary>
        /// <param name="enumDisplayText">描述内容</param>
        public EnumDescription(string enumDisplayText)
            : this(enumDisplayText, 5) { }


        public string EnumDisplayText
        {
            get { return this.enumDisplayText; }
        }



        public int EnumRank
        {
            get { return enumRank; }
        }



        public int EnumValue
        {
            get { return (int)fieldIno.GetValue(null); }
        }



        public string FieldName
        {
            get { return fieldIno.Name; }
        }



        #region  =========================================对枚举描述属性的解释相关函数



        /// <summary>
        /// 排序类型
        /// </summary>
        public enum SortType
        {

            /// <summary>
            ///按枚举顺序默认排序
            /// </summary>
            Default,

            /// <summary>
            /// 按描述值排序
            /// </summary>
            DisplayText,

            /// <summary>
            /// 按排序熵
            /// </summary>
            Rank

        }



        private static System.Collections.Hashtable cachedEnum = new Hashtable();

        /// <summary>
        /// 得到对枚举的描述文本
        /// </summary>
        /// <param name="enumType">枚举类型</param>
        /// <returns></returns>
        public static string GetEnumText(Type enumType)
        {

            EnumDescription[] eds = (EnumDescription[])enumType.GetCustomAttributes(typeof(EnumDescription), false);
            if (eds.Length != 1) return string.Empty;
            return eds[0].EnumDisplayText;
        }
        
        public static string GetFieldText<T>(object enumValue)
        {

            List<EnumDescription> descriptions = GetList<T>();
            T oEnumVal = (T)enumValue;
            foreach (EnumDescription ed in descriptions)
            {
                if (ed.fieldIno.Name == oEnumVal.ToString())
                {
                    return ed.EnumDisplayText;
                }
            }
            return string.Empty;

        }
              
        /// <summary>
        /// 获取自定义枚举列表
        /// </summary>        
        /// <param name="sortType"></param>
        /// <returns></returns>
        public static List<EnumDescription> GetList<T>(SortType sortType=SortType.Default)
        {
            Type enumType = typeof (T);
            List<EnumDescription> descriptions = new List<EnumDescription>();
            //缓存中没有找到，通过反射获得字段的描述信息
            if (cachedEnum.ContainsKey(enumType.FullName) == false)
            {
                FieldInfo[] fields = enumType.GetFields();
                List<EnumDescription> edAL = new List<EnumDescription>();
                foreach (FieldInfo fi in fields)
                {
                    object[] eds = fi.GetCustomAttributes(typeof(EnumDescription), false);
                    if (eds.Length != 1)
                    {
                        continue;
                    }
                    ((EnumDescription)eds[0]).fieldIno = fi;
                    edAL.Add((EnumDescription) eds[0]);
                }
                cachedEnum.Add(enumType.FullName, edAL);
            }

            descriptions = (List<EnumDescription>)cachedEnum[enumType.FullName];
            if (descriptions.Count <= 0) throw new NotSupportedException("枚举类型[" + enumType.Name + "]未定义属性EnumValueDescription");
            //按指定的属性冒泡排序
            for (int m = 0; m < descriptions.Count; m++)
            {
                //默认就不排序了
                if (sortType == SortType.Default) break;
                for (int n = m; n < descriptions.Count; n++)
                {
                    EnumDescription temp;
                    bool swap = false;
                    switch (sortType)
                    {
                        case SortType.Default:
                            break;
                        case SortType.DisplayText:
                            if (string.Compare(descriptions[m].EnumDisplayText, descriptions[n].EnumDisplayText) > 0) swap = true;
                            break;
                        case SortType.Rank:
                            if (descriptions[m].EnumRank > descriptions[n].EnumRank) swap = true;
                            break;
                    }
                    if (swap)
                    {
                        temp = descriptions[m];
                        descriptions[m] = descriptions[n];
                        descriptions[n] = temp;
                    }
                }

            }
            return descriptions;
        }

        #endregion
    }
}
